package com.netcracker.educenter.filestorage.servlets.files.uploading;

import com.netcracker.educenter.filestorage.configurator.Configurator;
import com.netcracker.educenter.filestorage.datasource.dao.FileAccess;
import com.netcracker.educenter.filestorage.datasource.dao.file.FileDAO;
import com.netcracker.educenter.filestorage.datasource.entity.File;
import com.netcracker.educenter.filestorage.servlets.utils.FileUtils;
import org.apache.log4j.Logger;

import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.sql.Timestamp;
import java.util.Collection;

@WebServlet(urlPatterns = "/user/Upload")
@MultipartConfig
public class UploadFileServlet extends HttpServlet {

    private static final Logger log = Logger.getLogger(UploadFileServlet.class.getName());
    private static final Path BASE_DIRECTORY = Paths.get(Configurator.getConfigurator().getPath());
    private static final String FILES_LIST_JSP_URL = Configurator.getConfigurator().getFileslistPageUrl();

    @Override
    public void service(HttpServletRequest request, HttpServletResponse response) {

        try {
            String userName = (String)request.getSession().getAttribute("authorized_user");

            Collection<Part> fileParts = request.getParts();
            for (Part filePart : fileParts) {
                savePartToFile(filePart, userName);
            }

            response.sendRedirect(request.getContextPath() + FILES_LIST_JSP_URL);

        } catch (IOException e) {
            log.error("I/O error", e);
        } catch (ServletException e) {
            log.error("Servlet error", e);
        }
    }

    private void savePartToFile(Part filePart, String userName) {

        String fileName = getFileName(filePart);
        if (fileName == null || fileName.trim().isEmpty()) {
            log.error(String.format("User: %s. Wrong name of file.", userName));
            return;
        }

        Path filePathOnServer = BASE_DIRECTORY.resolve(userName).resolve(fileName);
        try {
            Files.deleteIfExists(filePathOnServer);
            Files.createFile(filePathOnServer);
        } catch (IOException e) {
            log.error(String.format("User: %s. Cannot create file %s on server", userName, fileName), e);
            return;
        }

        try (InputStream inputStream = filePart.getInputStream();
             OutputStream outputStream = Files.newOutputStream(filePathOnServer)) {

            byte[] buffer = new byte[4096];
            FileUtils.copy(inputStream, outputStream, buffer);

            addFileDataToDB(fileName, filePathOnServer, userName);

        } catch (IOException e) {
            log.error(String.format("User: %s. Error in rewriting file %s", userName, fileName), e);
        }
    }

    private void addFileDataToDB(String fileName, Path filePath, String userName) {

        File fileInDB = new File();

        fileInDB.setFileName(fileName);
        fileInDB.setFilePath(String.format("\\%s\\", userName));
        fileInDB.setUserLogin(userName);
        fileInDB.setAdditionTime(new Timestamp(System.currentTimeMillis()));
        try {
            fileInDB.setFileSize(Files.size(filePath));
        } catch (IOException e) {
            log.warn(String.format("User: %s. Cannot get size of file %s", userName, fileName), e);
        }

        FileAccess fileDAO = new FileDAO();
        fileDAO.add(fileInDB);
    }

    private String getFileName(Part part) {

        String header = part.getHeader("Content-Disposition");

        for (String str : header.split(";")) {

            if (str.trim().startsWith("filename")) {
                return str.substring(str.indexOf('=') + 1).trim().replace("\"", "");
            }
        }
        return null;
    }
}
